using System;
using System.Collections.Generic;
using Be.Timvw.Framework.Domain.Generators;

namespace Be.Timvw.Framework.Domain.Ranges
{
    public class DiscreteValuesRange<T> : Range<T>, IDiscreteValuesRange<T> where T : IComparable<T>
    {
        private readonly IDiscreteValuesGenerator<T> discreteValuesGenerator;

        public DiscreteValuesRange(T begin, T end, IDiscreteValuesGenerator<T> discreteValuesGenerator)
        : base(begin, end)
        {
            this.discreteValuesGenerator = discreteValuesGenerator;
        }

        #region IDiscreteValuesRange<T> Members

        public bool IsCoveredBy(IEnumerable<IDiscreteValuesRange<T>> ranges)
        {
            T endOfRange = this.discreteValuesGenerator.MaxValue;

            T currentValueToCheck = this.Begin;
            while(currentValueToCheck.CompareTo(this.End) <= 0)
            {
                bool currentValueToCheckIsCovered = false;

                foreach(IDiscreteValuesRange<T> range in ranges)
                {
                    if(range.Includes(currentValueToCheck))
                    {
                        currentValueToCheckIsCovered = true;

                        if(range.End.CompareTo(endOfRange) < 0)
                        {
                            currentValueToCheck = this.discreteValuesGenerator.GenerateNextValue(range.End);
                        }
                        else
                        {
                            return true;
                        }
                    }
                }

                if(!currentValueToCheckIsCovered)
                {
                    return false;
                }
            }

            return true;
        }

        public IEnumerable<T> Values
        {
            get
            {
                for(T value = this.Begin; value.CompareTo(this.End) <= 0; value = this.discreteValuesGenerator.GenerateNextValue(value))
                {
                    yield return value;
                }
            }
        }

        #endregion
    }
}